package com.dwj.auto.comment.common.wechat;

import com.alibaba.fastjson.JSONObject;
import com.dwj.auto.comment.common.enums.WxEventEnum;
import com.dwj.auto.comment.common.enums.WxTextCommand;
import com.dwj.auto.comment.common.utils.SpringUtil;
import com.dwj.auto.comment.common.wechat.handler.WxMessageHandler;
import com.dwj.auto.comment.model.wechat.WxMessage;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @ClassName MessageRecipient
 * @Description 微信消息接收者
 * @Author dwjian
 * @Date 2020/12/26 19:42
 */
@Slf4j
@NoArgsConstructor
public class MessageRecipient {

    private static final String AES = "aes";
    private static final String RAW = "raw";
    private static final String MSG_SIGNATURE = "msg_signature";
    private static final String ENCRYPT_TYPE = "encrypt_type";

    private WxMessage wxMessage;

    MessageRecipient(HttpServletRequest request, String timestamp, String nonce) {
        WxMessage wxMessage = receive(request, timestamp, nonce);
        if(wxMessage != null){
            this.wxMessage = wxMessage;
        }

    }

    public WxMessage receive(HttpServletRequest request, String timestamp, String nonce) {
        WxMpService mpService = SpringUtil.getBean(WxMpService.class);
        WxMpXmlMessage wxMpXmlMessage = null;
        String encryptType = StringUtils.isBlank(request.getParameter(ENCRYPT_TYPE)) ? RAW : request.getParameter(ENCRYPT_TYPE);
        if (RAW.equals(encryptType)) {
            try {
                wxMpXmlMessage = WxMpXmlMessage.fromXml(request.getInputStream());
            } catch (IOException e) {
                log.info("明文消息解析异常", e);
            }
        } else if (AES.equals(encryptType)) {
            try {
                String msgSignature = request.getParameter(MSG_SIGNATURE);
                wxMpXmlMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), mpService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);
            } catch (IOException e) {
                log.info("密文消息解析异常", e);
            }
        }
        if(wxMpXmlMessage != null){
            log.info("接收到微信消息：" +  JSONObject.toJSONString(wxMpXmlMessage));
            if(WxConsts.XmlMsgType.EVENT.equals(wxMpXmlMessage.getMsgType())){
                return new WxMessage(wxMpXmlMessage.getFromUser(), wxMpXmlMessage.getToUser(), wxMpXmlMessage.getMsgType(), wxMpXmlMessage.getEvent());
            }else if(WxConsts.XmlMsgType.TEXT.equals(wxMpXmlMessage.getMsgType())) {
                return new WxMessage(wxMpXmlMessage.getFromUser(), wxMpXmlMessage.getToUser(), wxMpXmlMessage.getMsgType(), wxMpXmlMessage.getContent());
            }
        }
        return null;
    }

    public String execute(){
        if(wxMessage != null && StringUtils.isNotEmpty(StringUtils.trim(wxMessage.getContent()))){
            WxMessageHandler handler = null;
            if(WxConsts.XmlMsgType.EVENT.equals(wxMessage.getMessageType())){
                String content = StringUtils.trim(wxMessage.getContent());
                WxEventEnum event = WxEventEnum.getByEvent(content);
                if(event != null){
                    handler = SpringUtil.getBean(event.getHandler());
                }
            }
            if(WxConsts.XmlMsgType.TEXT.equals(wxMessage.getMessageType())){
                String content = StringUtils.trim(wxMessage.getContent());
                WxTextCommand textCommand = WxTextCommand.match(content);
                if(textCommand != null){
                    handler = SpringUtil.getBean(textCommand.getHandler());
                }
            }
            if(handler != null){
                String replyMessage = handler.dealMessage(wxMessage);
                if(StringUtils.isNotEmpty(replyMessage)){
                    return buildMessage(replyMessage, wxMessage.getPublicOpenid(), wxMessage.getOpenId());
                }
            }
        }
        return null;
    }

    private String buildMessage(String content, String fromUser, String toUser){
        return WxMpXmlOutTextMessage.TEXT().toUser(toUser).fromUser(fromUser).content(new String(content.getBytes(), StandardCharsets.ISO_8859_1)).build().toXml();
    }
}
